﻿/*
    Copyright(c) 2015 Neodymium

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

/*
   This file contains only SHA1 hashes of all interesting values. There is NO key.
*/


//shamelessly stolen

using CodeWalker.Core.Properties;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace CodeWalker.GameFiles
{
    public static class GTA5Keys
    {
        public static string ToS = "(c)2017";

        // aes decryption/encryption key...
        public static byte[] PC_AES_KEY; // 32

        // ng decryption/encryption expanded keys...      
        public static byte[][] PC_NG_KEYS; // 101, 272

        // ng decryption tables...       
        public static uint[][][] PC_NG_DECRYPT_TABLES; // 17, 16, 256

        // ng encryption tables...
        // -> some of these tables can be calculated from decryption tables
        public static uint[][][] PC_NG_ENCRYPT_TABLES; // 17, 16, 256

        // ng encryption look-up-tables
        // -> some of these look-up-tables can be calculated from decryption tables
        public static GTA5NGLUT[][] PC_NG_ENCRYPT_LUTs; // 17, 16

        // hash lookup-table...
        public static byte[] PC_LUT; // 256


        public static uint[] PC_AWC_KEY; // 16



        public static void Generate(byte[] exeData, Action<string> updateStatus) //Stream exeStr)// 
        {
            var exeStr = new MemoryStream(exeData);

            updateStatus("Searching for AES key...");
            PC_AES_KEY = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_AES_KEY_HASH, 0x20);
            //updateStatus("aes key found");

            updateStatus("Searching for NG keys...");
            PC_NG_KEYS = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_KEY_HASHES, 0x110);
            //updateStatus("ng keys found");

            updateStatus("Searching for NG decrypt tables...");
            var tabs = HashSearch.SearchHashes(exeStr, GTA5KeyHashes.PC_NG_DECRYPT_TABLE_HASHES, 0x400);
            //updateStatus("ng decrypt tables found");

            updateStatus("Searching for NG hash lookup tables...");
            // 17 rounds
            PC_NG_DECRYPT_TABLES = new uint[17][][];
            for (int i = 0; i < 17; i++)
            {
                // 
                PC_NG_DECRYPT_TABLES[i] = new uint[16][];
                for (int j = 0; j < 16; j++)
                {
                    var buf = tabs[j + 16 * i];
                    PC_NG_DECRYPT_TABLES[i][j] = new uint[256];
                    Buffer.BlockCopy(buf, 0, PC_NG_DECRYPT_TABLES[i][j], 0, 1024);
                }
            }

            PC_LUT = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_LUT_HASH, 0x100);
            //updateStatus("ng hash LUTs found");



            updateStatus("Calculating NG encryption tables...");
            PC_NG_ENCRYPT_TABLES = new uint[17][][];
            for (int i = 0; i < 17; i++)
            {
                PC_NG_ENCRYPT_TABLES[i] = new uint[16][];
                for (int j = 0; j < 16; j++)
                {
                    PC_NG_ENCRYPT_TABLES[i][j] = new uint[256];
                    for (int k = 0; k < 256; k++)
                    {
                        PC_NG_ENCRYPT_TABLES[i][j][k] = 0;
                    }
                }
            }

            PC_NG_ENCRYPT_LUTs = new GTA5NGLUT[17][];
            for (int i = 0; i < 17; i++)
            {
                PC_NG_ENCRYPT_LUTs[i] = new GTA5NGLUT[16];
                for (int j = 0; j < 16; j++)
                    PC_NG_ENCRYPT_LUTs[i][j] = new GTA5NGLUT();
            }




            updateStatus("Calculating NG encryption tables (1/17)...");
            PC_NG_ENCRYPT_TABLES[0] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[0]);
            //updateStatus("ng encrypt table 1 of 17 calculated");

            updateStatus("Calculating NG encryption tables (2/17)...");
            PC_NG_ENCRYPT_TABLES[1] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[1]);
            //updateStatus("ng encrypt table 2 of 17 calculated");

            for (int k = 2; k <= 15; k++)
            {
                updateStatus("Calculating NG encryption tables (" + (k + 1).ToString() + "/17)...");
                PC_NG_ENCRYPT_LUTs[k] = LookUpTableGenerator.BuildLUTs2(PC_NG_DECRYPT_TABLES[k]);
                //updateStatus("ng encrypt table " + (k + 1).ToString() + " of 17 calculated");
            }

            updateStatus("Calculating NG encryption tables (17/17)...");
            PC_NG_ENCRYPT_TABLES[16] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[16]);
            //updateStatus("ng encrypt table 17 of 17 calculated");

            updateStatus("Complete.");
        }


        public static void GenerateV2(byte[] exeData, Action<string> updateStatus)
        {
            var exeStr = new MemoryStream(exeData);

            updateStatus?.Invoke("Searching for AES key...");
            PC_AES_KEY = HashSearch.SearchHash(exeStr, GTA5KeyHashes.PC_AES_KEY_HASH, 0x20);

            updateStatus?.Invoke("Complete.");
        }



        public static void LoadFromPath(string path = ".\\Keys", string key = null)
        {
            //PC_AES_KEY = File.ReadAllBytes(path + "\\gtav_aes_key.dat");
            //PC_NG_KEYS = CryptoIO.ReadNgKeys(path + "\\gtav_ng_key.dat");
            //PC_NG_DECRYPT_TABLES = CryptoIO.ReadNgTables(path + "\\gtav_ng_decrypt_tables.dat");
            ////PC_NG_ENCRYPT_TABLES = CryptoIO.ReadNgTables(path + "\\gtav_ng_encrypt_tables.dat");
            ////PC_NG_ENCRYPT_LUTs = CryptoIO.ReadNgLuts(path + "\\gtav_ng_encrypt_luts.dat");
            //PC_LUT = File.ReadAllBytes(path + "\\gtav_hash_lut.dat");

            //GenerateMagicData(path);
            UseMagicData(path, key);
        }

        public static void SaveToPath(string path = ".\\Keys")
        {
            File.WriteAllBytes(path + "\\gtav_aes_key.dat", PC_AES_KEY);
            CryptoIO.WriteNgKeys(path + "\\gtav_ng_key.dat", PC_NG_KEYS);
            CryptoIO.WriteNgTables(path + "\\gtav_ng_decrypt_tables.dat", PC_NG_DECRYPT_TABLES);
            CryptoIO.WriteNgTables(path + "\\gtav_ng_encrypt_tables.dat", PC_NG_ENCRYPT_TABLES);
            CryptoIO.WriteLuts(path + "\\gtav_ng_encrypt_luts.dat", PC_NG_ENCRYPT_LUTs);
            File.WriteAllBytes(path + "\\gtav_hash_lut.dat", PC_LUT);
        }




        private static void GenerateMagicData(string path = ".\\Keys")
        {
            byte[] b1 = File.ReadAllBytes(path + "\\gtav_ng_key.dat");
            byte[] b2 = File.ReadAllBytes(path + "\\gtav_ng_decrypt_tables.dat");
            byte[] b3 = File.ReadAllBytes(path + "\\gtav_hash_lut.dat");
            byte[] b4 = File.ReadAllBytes(path + "\\gtav_awc_key.dat");

            int bl = b1.Length + b2.Length + b3.Length + b4.Length;
            byte[] b = new byte[bl];
            int bp = 0;
            Buffer.BlockCopy(b1, 0, b, bp, b1.Length); bp += b1.Length; // 27472
            Buffer.BlockCopy(b2, 0, b, bp, b2.Length); bp += b2.Length; // 278528
            Buffer.BlockCopy(b3, 0, b, bp, b3.Length); bp += b3.Length; // 256
            Buffer.BlockCopy(b4, 0, b, bp, b4.Length); bp += b4.Length; // 16

            byte[] db = null;
            using (MemoryStream dms = new MemoryStream())
            {
                using (DeflateStream ds = new DeflateStream(dms, CompressionMode.Compress))
                {
                    ds.Write(b, 0, b.Length);
                    ds.Close();
                    db = dms.ToArray();
                }
            }

            if (db == null)
            {
                throw new Exception("Error deflating data.");
            }

            db = GTACrypto.EncryptAESData(db, PC_AES_KEY);


            Random rnd = new Random((int)JenkHash.GenHash(PC_AES_KEY));
            int dbl = db.Length;
            byte[] rb1 = new byte[dbl];
            byte[] rb2 = new byte[dbl];
            byte[] rb3 = new byte[dbl];
            byte[] rb4 = new byte[dbl];
            rnd.NextBytes(rb1);
            rnd.NextBytes(rb2);
            rnd.NextBytes(rb3);
            rnd.NextBytes(rb4);
            byte[] fb = new byte[dbl];
            for (int i = 0; i < dbl; i++)
            {
                fb[i] = (byte)((db[i] + rb1[i] + rb2[i] + rb3[i] + rb4[i]) & 0xFF);
            }

            File.WriteAllBytes(path + "\\magic.dat", fb);

        }

        private static void UseMagicData(string path, string key)
        {

            if (string.IsNullOrEmpty(key))
            {
                byte[] exedata = File.ReadAllBytes(path + "\\gta5.exe");
                GenerateV2(exedata, null);
            }
            else
            {
                PC_AES_KEY = Convert.FromBase64String(key);
            }
            //GenerateMagicData();


            Random rnd = new Random((int)JenkHash.GenHash(PC_AES_KEY));
            byte[] m = Resources.magic;
            int dbl = m.Length;
            byte[] rb1 = new byte[dbl];
            byte[] rb2 = new byte[dbl];
            byte[] rb3 = new byte[dbl];
            byte[] rb4 = new byte[dbl];
            rnd.NextBytes(rb1);
            rnd.NextBytes(rb2);
            rnd.NextBytes(rb3);
            rnd.NextBytes(rb4);
            byte[] db = new byte[dbl];
            for (int i = 0; i < dbl; i++)
            {
                db[i] = (byte)((m[i] - rb1[i] - rb2[i] - rb3[i] - rb4[i]) & 0xFF);
            }

            db = GTACrypto.DecryptAESData(db, PC_AES_KEY);

            byte[] b = null;
            using (MemoryStream dms = new MemoryStream(db))
            {
                using (DeflateStream ds = new DeflateStream(dms, CompressionMode.Decompress))
                {
                    using (MemoryStream outstr = new MemoryStream())
                    {
                        ds.CopyTo(outstr);
                        b = outstr.GetBuffer();
                    }
                }
            }
            if (b == null)
            {
                throw new Exception("Error inflating magic data.");
            }

            byte[] b1 = new byte[27472];
            byte[] b2 = new byte[278528];
            byte[] b3 = new byte[256];
            uint[] b4 = new uint[4];
            int bp = 0;
            Buffer.BlockCopy(b, bp, b1, 0, b1.Length); bp += b1.Length; // 27472
            Buffer.BlockCopy(b, bp, b2, 0, b2.Length); bp += b2.Length; // 278528
            Buffer.BlockCopy(b, bp, b3, 0, b3.Length); bp += b3.Length; // 256
            Buffer.BlockCopy(b, bp, b4, 0, b4.Length * 4); bp += b4.Length; // 16

            PC_NG_KEYS = CryptoIO.ReadNgKeys(b1);
            PC_NG_DECRYPT_TABLES = CryptoIO.ReadNgTables(b2);
            PC_LUT = b3;
            PC_AWC_KEY = b4;
        }


    }




    public static class GTA5KeyHashes
    {
        // aes decryption/encryption key...
        public static byte[] PC_AES_KEY_HASH = new byte[] { 0xA0, 0x79, 0x61, 0x28, 0xA7, 0x75, 0x72, 0x0A, 0xC2, 0x04, 0xD9, 0x81, 0x9F, 0x68, 0xC1, 0x72, 0xE3, 0x95, 0x2C, 0x6D };

        // ng decryption/encryption expanded keys...
        public static byte[][] PC_NG_KEY_HASHES = new byte[101][] {
            new byte[] { 0xEB, 0x09, 0x15, 0x12, 0x03, 0x97, 0xCE, 0x2E, 0x17, 0x82, 0x8D, 0xD7, 0x7E, 0x32, 0x18, 0xD9, 0x77, 0xA1, 0x85, 0xF7 },
            new byte[] { 0xD7, 0x40, 0xB3, 0xC8, 0x9F, 0xE3, 0xA1, 0x9A, 0x92, 0x65, 0xDC, 0xEE, 0xFB, 0x45, 0x4C, 0x16, 0x2D, 0xB4, 0x53, 0x68 },
            new byte[] { 0x85, 0xF4, 0x3E, 0x5B, 0xAB, 0x4A, 0xBC, 0xAD, 0x76, 0xD8, 0x07, 0x15, 0xBB, 0x39, 0x32, 0xE9, 0xE7, 0xEC, 0xC5, 0xE2 },
            new byte[] { 0xB8, 0x6D, 0x64, 0x1E, 0x44, 0x17, 0xF3, 0xDD, 0xD8, 0x01, 0x98, 0x55, 0x14, 0xEF, 0x79, 0x73, 0x22, 0xF2, 0xD6, 0x57 },
            new byte[] { 0xE1, 0x27, 0xAE, 0xDB, 0x60, 0x43, 0x51, 0x31, 0xAB, 0x6D, 0x44, 0xF8, 0xBC, 0x02, 0x46, 0xB9, 0x52, 0x38, 0xB1, 0x0B },
            new byte[] { 0x15, 0xBE, 0x8F, 0x36, 0xB7, 0xE7, 0x26, 0xB3, 0x28, 0x7A, 0x77, 0x85, 0x88, 0x85, 0x94, 0x12, 0xEB, 0x0C, 0xAA, 0x66 },
            new byte[] { 0x28, 0x72, 0x6A, 0xEC, 0x3B, 0x14, 0x19, 0x7C, 0x0E, 0x54, 0x8B, 0xAA, 0x5C, 0x8D, 0xF5, 0x12, 0x84, 0x98, 0xC4, 0x75 },
            new byte[] { 0xAD, 0xDC, 0xB1, 0xBE, 0xF3, 0x98, 0x6E, 0x4A, 0x3A, 0x31, 0xF4, 0xED, 0xA4, 0xDB, 0xCE, 0xB6, 0x1A, 0x6C, 0x91, 0x47 },
            new byte[] { 0xB9, 0xD4, 0xF6, 0xA1, 0x19, 0x90, 0x66, 0x47, 0xD1, 0x85, 0x83, 0x08, 0x3F, 0xCF, 0x4E, 0x1D, 0xFB, 0x0F, 0x74, 0x26 },
            new byte[] { 0x0F, 0x3F, 0x35, 0x99, 0x1A, 0xC0, 0xB1, 0xAA, 0xB1, 0x12, 0x84, 0x05, 0x9D, 0x96, 0x9B, 0x4A, 0xC7, 0xA0, 0x3B, 0x13 },
            new byte[] { 0x3B, 0xA9, 0x01, 0x6A, 0x98, 0x44, 0x47, 0x0D, 0x46, 0x33, 0xEF, 0x2E, 0x6A, 0xC6, 0x3C, 0x77, 0xAF, 0x9A, 0xCC, 0x99 },
            new byte[] { 0xDB, 0xF6, 0x28, 0x3C, 0xF8, 0x2E, 0xDC, 0x4E, 0x1D, 0xA5, 0xCB, 0xDD, 0xA6, 0xFA, 0x21, 0x8E, 0xB8, 0xAE, 0x72, 0xBB },
            new byte[] { 0xA4, 0xBF, 0x04, 0xE7, 0x2F, 0x5E, 0x9D, 0xBD, 0x7B, 0xF8, 0x50, 0x77, 0x67, 0x69, 0xB6, 0x2F, 0x56, 0x8D, 0xC7, 0xF9 },
            new byte[] { 0x6A, 0xAE, 0xA0, 0x64, 0xB9, 0xBB, 0xE7, 0xF1, 0xED, 0xAE, 0xF4, 0x7F, 0x8B, 0x83, 0x5F, 0x0E, 0xA8, 0xD5, 0x06, 0x6B },
            new byte[] { 0x1B, 0xB1, 0x18, 0xB6, 0xC1, 0x19, 0x2B, 0x98, 0xAF, 0x11, 0x98, 0xCB, 0x73, 0xC3, 0xE1, 0xE5, 0xAE, 0x48, 0xDD, 0xA1 },
            new byte[] { 0x4B, 0x97, 0x33, 0x2A, 0x27, 0x28, 0xFF, 0x46, 0xD8, 0xBD, 0x73, 0x61, 0x5D, 0x14, 0xCF, 0x47, 0xD3, 0xC2, 0xC9, 0xA0 },
            new byte[] { 0x66, 0x15, 0x42, 0x97, 0x46, 0x57, 0x96, 0x16, 0x5A, 0x87, 0x6F, 0x5E, 0xF6, 0x84, 0xB3, 0xA0, 0xDB, 0x5C, 0x6D, 0x58 },
            new byte[] { 0xF5, 0xB5, 0xE7, 0x6F, 0x77, 0xFE, 0x13, 0xAC, 0xC2, 0xF9, 0x2D, 0xEA, 0xD0, 0xD9, 0xC5, 0xCD, 0x05, 0x9A, 0xC0, 0x48 },
            new byte[] { 0x8A, 0x0C, 0x59, 0xBD, 0x88, 0x0D, 0x28, 0x18, 0x3D, 0xE9, 0x8B, 0x2C, 0xB0, 0x9A, 0xD0, 0xE1, 0xBE, 0x0C, 0x03, 0x23 },
            new byte[] { 0x26, 0xA7, 0xBC, 0x77, 0x22, 0x5F, 0x67, 0xBC, 0x3D, 0xD5, 0xD5, 0x05, 0x53, 0xB9, 0xD8, 0x2D, 0xD2, 0x80, 0x80, 0x26 },
            new byte[] { 0x66, 0x40, 0x17, 0x57, 0x5B, 0x70, 0x7B, 0x76, 0x71, 0x91, 0x56, 0xED, 0xFB, 0x5E, 0xC9, 0x7B, 0x55, 0x77, 0x5C, 0x40 },
            new byte[] { 0xEC, 0x90, 0xAB, 0xB0, 0x46, 0x6E, 0x62, 0xF1, 0xB9, 0xDB, 0xFB, 0xF2, 0x4E, 0xAE, 0x2F, 0x20, 0x54, 0x74, 0xA1, 0xDA },
            new byte[] { 0x4A, 0xA3, 0x51, 0x73, 0x61, 0x98, 0x34, 0x18, 0x8D, 0x9E, 0x76, 0x59, 0x89, 0x68, 0x2A, 0x1C, 0x1A, 0x2D, 0x27, 0x77 },
            new byte[] { 0xB5, 0xDF, 0x02, 0x8B, 0xB9, 0x86, 0x0C, 0x84, 0x0D, 0x75, 0x45, 0x77, 0xFF, 0x9C, 0x02, 0xEB, 0x7D, 0x65, 0x09, 0x29 },
            new byte[] { 0x86, 0x26, 0xF9, 0xF0, 0xA7, 0xA9, 0x79, 0x55, 0x72, 0x14, 0x6F, 0x92, 0xAC, 0xC1, 0x06, 0x12, 0xCD, 0x60, 0x75, 0x7D },
            new byte[] { 0xCD, 0xA4, 0xC6, 0x4F, 0x0F, 0x94, 0x65, 0x11, 0x57, 0x4D, 0xF5, 0xC6, 0xA0, 0x19, 0x8E, 0x7B, 0x51, 0xEE, 0xBC, 0x07 },
            new byte[] { 0xC2, 0xB6, 0x51, 0x28, 0xC5, 0xBF, 0x14, 0x0C, 0xDD, 0x58, 0xFB, 0xAE, 0xFF, 0x43, 0x4A, 0x69, 0x89, 0x23, 0x37, 0x1A },
            new byte[] { 0x14, 0x30, 0xFF, 0x46, 0xEA, 0xFB, 0xCA, 0x55, 0xDF, 0x49, 0x4A, 0x1B, 0x7F, 0xCD, 0x5F, 0xDD, 0xC7, 0x6E, 0x71, 0x2E },
            new byte[] { 0xD0, 0xB6, 0x7E, 0x92, 0xA0, 0xFB, 0x5A, 0x74, 0xCB, 0x2C, 0xFA, 0x60, 0x25, 0xAB, 0xE4, 0x7B, 0x88, 0xE4, 0xD8, 0xAE },
            new byte[] { 0xAE, 0xDB, 0x38, 0xAA, 0x93, 0xEA, 0x10, 0xBC, 0xFF, 0x5D, 0x7B, 0xAB, 0x8F, 0x95, 0x6F, 0x4A, 0x03, 0xA8, 0xF2, 0xF2 },
            new byte[] { 0x81, 0xBF, 0xDA, 0x4A, 0x64, 0x97, 0x3C, 0x36, 0x64, 0x52, 0x13, 0xAE, 0xB5, 0x39, 0xD3, 0x1D, 0xF6, 0xEA, 0x8C, 0x99 },
            new byte[] { 0x9A, 0x1D, 0xE6, 0x96, 0x0F, 0x2C, 0xF2, 0x3F, 0x46, 0xCD, 0x14, 0x04, 0xD4, 0xEE, 0x6E, 0xA7, 0x73, 0xE9, 0x1A, 0x8A },
            new byte[] { 0xB6, 0xE6, 0xD2, 0xFA, 0xE3, 0x95, 0x1C, 0xDD, 0x28, 0x6C, 0x97, 0xA2, 0xE1, 0x54, 0x0F, 0x72, 0xAB, 0x63, 0x20, 0x5D },
            new byte[] { 0xCF, 0x57, 0x29, 0xAF, 0x92, 0x38, 0x1D, 0x0B, 0x5F, 0xCE, 0x3F, 0x11, 0x77, 0x5E, 0x75, 0x96, 0xBE, 0xBD, 0x27, 0x25 },
            new byte[] { 0x19, 0x8E, 0xC1, 0x12, 0xFC, 0xB3, 0xD9, 0x93, 0x8A, 0x6C, 0xA5, 0x13, 0x5D, 0xFB, 0x6D, 0x77, 0xF6, 0xDC, 0x2F, 0xEE },
            new byte[] { 0x04, 0x81, 0x55, 0x6C, 0xD2, 0x59, 0xFB, 0xAD, 0xF8, 0xE1, 0xF1, 0xA7, 0x85, 0x02, 0xA6, 0xF4, 0x7F, 0xA2, 0x2F, 0x62 },
            new byte[] { 0x88, 0x0E, 0xBD, 0x6A, 0xA6, 0x47, 0x17, 0xAD, 0xA1, 0xE6, 0xE0, 0x97, 0x74, 0x53, 0x9C, 0xFE, 0x38, 0xFB, 0x91, 0x52 },
            new byte[] { 0xA1, 0xAE, 0x7D, 0x57, 0x6F, 0xF8, 0x85, 0xE2, 0xA8, 0xFD, 0xB6, 0x01, 0xE3, 0x55, 0x65, 0x60, 0xCD, 0xD8, 0xD3, 0x30 },
            new byte[] { 0x80, 0x26, 0xA6, 0x9B, 0x78, 0x2C, 0x0F, 0xD6, 0x4C, 0xE5, 0x19, 0x42, 0xAC, 0xC8, 0x42, 0x07, 0x54, 0x28, 0xFF, 0x14 },
            new byte[] { 0x89, 0x03, 0xCA, 0x8A, 0x1F, 0xD4, 0x73, 0x0F, 0x68, 0x8A, 0x61, 0x0D, 0xAC, 0xFA, 0x64, 0x7D, 0xC8, 0xAA, 0x96, 0xF2 },
            new byte[] { 0x99, 0x37, 0x9A, 0x14, 0x51, 0x14, 0xB5, 0xD5, 0x99, 0x6A, 0x57, 0x9C, 0xF2, 0xE3, 0x38, 0xAF, 0x70, 0x9C, 0x49, 0xC9 },
            new byte[] { 0x0F, 0x2D, 0x55, 0x01, 0x05, 0x44, 0x55, 0x66, 0x0E, 0xFC, 0x4F, 0xB2, 0xBA, 0x29, 0x9B, 0x5B, 0xCA, 0x29, 0xBC, 0x1A },
            new byte[] { 0xF1, 0x38, 0x5B, 0x67, 0xF4, 0xAF, 0xBE, 0xC9, 0x4F, 0x7A, 0x00, 0xA6, 0x8B, 0x0E, 0x70, 0x0B, 0xA8, 0x6A, 0x81, 0xEE },
            new byte[] { 0x36, 0xB1, 0x05, 0xB7, 0xED, 0x94, 0xCA, 0x95, 0xD3, 0x9E, 0x1C, 0xE2, 0x4D, 0xD9, 0x71, 0x66, 0x46, 0xF2, 0x9B, 0x59 },
            new byte[] { 0x75, 0xC6, 0x12, 0x28, 0xE2, 0x7F, 0x61, 0xF0, 0x4B, 0x71, 0xCD, 0x4D, 0xE8, 0xE3, 0x9A, 0xE4, 0x20, 0xC2, 0x5C, 0xE6 },
            new byte[] { 0x37, 0x0E, 0x44, 0xD7, 0x27, 0x99, 0xE6, 0x2B, 0xB1, 0x34, 0xFA, 0xB7, 0x45, 0x33, 0xF7, 0xCD, 0x3C, 0x0D, 0x77, 0xF5 },
            new byte[] { 0xAA, 0x46, 0xCE, 0xA4, 0x4D, 0x0A, 0xCE, 0xDC, 0x81, 0x59, 0xEC, 0xCF, 0x1E, 0x0F, 0xB4, 0x15, 0xE8, 0x27, 0x18, 0x9E },
            new byte[] { 0xC0, 0x0D, 0x76, 0xBD, 0x70, 0x3B, 0x1B, 0x6F, 0x11, 0x1A, 0x84, 0x2B, 0x0B, 0x19, 0xC6, 0x55, 0xC6, 0x7F, 0x0F, 0x6C },
            new byte[] { 0xF7, 0xA9, 0x4E, 0x1F, 0x06, 0x03, 0xB9, 0xD7, 0x36, 0x0A, 0x34, 0x7F, 0x41, 0x94, 0x1D, 0x57, 0xA1, 0xD0, 0x0A, 0xFA },
            new byte[] { 0xCC, 0xAF, 0x7E, 0x30, 0x26, 0xDE, 0xC8, 0xC9, 0x3C, 0x27, 0x8F, 0x40, 0x32, 0xF5, 0xAB, 0xC4, 0xCB, 0x90, 0x6D, 0xAE },
            new byte[] { 0x39, 0x5D, 0x47, 0xF2, 0xF8, 0x91, 0xFF, 0xD7, 0xE1, 0x75, 0xF3, 0xA0, 0xFA, 0xC3, 0xC2, 0x86, 0x0D, 0xE1, 0xE2, 0x45 },
            new byte[] { 0xB1, 0xC9, 0x1C, 0x3E, 0x77, 0x20, 0xEE, 0x9C, 0xBC, 0xA4, 0x1E, 0x3E, 0x6C, 0x34, 0x40, 0x08, 0x09, 0x27, 0xA7, 0xF5 },
            new byte[] { 0x61, 0x92, 0x6E, 0xF1, 0xA1, 0x0F, 0x71, 0x25, 0x1C, 0xEE, 0xE4, 0x94, 0x8B, 0x29, 0xEA, 0x7E, 0x90, 0x36, 0xE5, 0xE5 },
            new byte[] { 0xD5, 0xDE, 0x91, 0xB6, 0x37, 0x2C, 0x00, 0x73, 0xB8, 0x80, 0x17, 0x19, 0xF4, 0xC0, 0xCE, 0xE6, 0xDF, 0xFB, 0xB5, 0xFC },
            new byte[] { 0x01, 0xE0, 0x43, 0xC0, 0xDA, 0x86, 0xE9, 0x73, 0x51, 0xFA, 0x2E, 0x4A, 0xF1, 0xA4, 0xF6, 0x5B, 0x6A, 0x97, 0x7B, 0x39 },
            new byte[] { 0x80, 0x85, 0x51, 0x20, 0xBA, 0x2E, 0x31, 0x6B, 0xD7, 0xB8, 0x09, 0x30, 0xA5, 0x60, 0xCC, 0x0E, 0x8B, 0x9A, 0x91, 0xD7 },
            new byte[] { 0x06, 0x06, 0xC0, 0xB8, 0x2A, 0x97, 0x94, 0x7D, 0x25, 0x2C, 0xD3, 0x87, 0x8A, 0x9D, 0xBE, 0xFD, 0xEC, 0x17, 0xB4, 0x98 },
            new byte[] { 0x5F, 0xD7, 0x58, 0xEB, 0x71, 0x3A, 0x4B, 0xE0, 0x8E, 0x29, 0x2A, 0xC7, 0x55, 0x75, 0x91, 0xA7, 0x06, 0xA3, 0x2B, 0x2C },
            new byte[] { 0x2A, 0x3C, 0x3F, 0xA1, 0x1C, 0xFA, 0x0F, 0x5F, 0x75, 0x4C, 0x65, 0x56, 0xE0, 0xD9, 0x52, 0x06, 0x11, 0xD6, 0xB4, 0x0B },
            new byte[] { 0xFA, 0xE6, 0xB7, 0x90, 0xB7, 0x87, 0x91, 0xA9, 0x10, 0x84, 0xA1, 0xB5, 0xCA, 0x9A, 0x70, 0x7D, 0x56, 0x07, 0xE4, 0x5F },
            new byte[] { 0x8F, 0x9A, 0xA7, 0x48, 0xF1, 0x14, 0x50, 0x67, 0xFA, 0xC8, 0x0E, 0x18, 0x26, 0x48, 0xED, 0x61, 0x8C, 0x84, 0xAC, 0xCE },
            new byte[] { 0x39, 0xB7, 0xFD, 0x2F, 0xB4, 0xEB, 0x43, 0xE3, 0xC1, 0xCE, 0xF1, 0x5D, 0x9E, 0xF7, 0x16, 0xA6, 0x81, 0x12, 0x25, 0xBA },
            new byte[] { 0xEB, 0x28, 0xF6, 0x34, 0x62, 0x49, 0xA7, 0x99, 0x16, 0x2E, 0x0B, 0xEE, 0xE5, 0x58, 0x92, 0x90, 0xAE, 0x8C, 0xCF, 0x3F },
            new byte[] { 0x51, 0xDA, 0xC7, 0x9D, 0x41, 0x87, 0xB3, 0x94, 0x43, 0xFE, 0x3B, 0xC7, 0xF9, 0x19, 0x72, 0x47, 0x55, 0xAD, 0x27, 0x19 },
            new byte[] { 0x0C, 0xAF, 0xFE, 0x08, 0x02, 0x3E, 0xD8, 0xB5, 0xAC, 0x2A, 0x14, 0x18, 0xBD, 0x42, 0x05, 0xAB, 0xD7, 0x43, 0x3E, 0x9B },
            new byte[] { 0x0F, 0x0B, 0x7A, 0x98, 0xE8, 0x89, 0x63, 0xE9, 0x16, 0xC6, 0x78, 0x78, 0x86, 0x18, 0x7F, 0x3F, 0xCB, 0x7F, 0x9C, 0x39 },
            new byte[] { 0xB6, 0x4A, 0x86, 0x10, 0xAB, 0x90, 0xE1, 0xF2, 0xED, 0xD2, 0x2B, 0xAC, 0x42, 0x38, 0x33, 0x1A, 0xF8, 0x95, 0xB7, 0x5B },
            new byte[] { 0x57, 0x77, 0x12, 0x3E, 0x8F, 0x6A, 0x2B, 0x7F, 0x95, 0x14, 0x14, 0xA0, 0x9E, 0xE0, 0x1B, 0x36, 0x1C, 0x3C, 0xA1, 0xD0 },
            new byte[] { 0x24, 0x87, 0x11, 0x86, 0x54, 0xBC, 0x51, 0x30, 0x3E, 0xA7, 0x79, 0xC5, 0xB2, 0x64, 0x76, 0x97, 0x78, 0x31, 0x3E, 0xBB },
            new byte[] { 0x75, 0x60, 0xA9, 0x20, 0xA9, 0x1A, 0xE7, 0x49, 0x1B, 0x14, 0xD2, 0x7D, 0xEF, 0x75, 0xFB, 0x0B, 0xFC, 0x26, 0x8F, 0xA6 },
            new byte[] { 0xB0, 0x7B, 0x51, 0x09, 0x5D, 0x44, 0xBA, 0xAB, 0x05, 0xF8, 0x9B, 0x5E, 0x8A, 0xC1, 0xBC, 0x73, 0xE1, 0x32, 0x64, 0xA5 },
            new byte[] { 0x1F, 0x8B, 0x33, 0x1D, 0xEF, 0x6E, 0xBE, 0x11, 0x21, 0x2F, 0x2B, 0x61, 0xB8, 0x5E, 0xCC, 0xED, 0xEA, 0xA7, 0x21, 0xD9 },
            new byte[] { 0x72, 0x71, 0x1E, 0xA9, 0x46, 0x60, 0x3E, 0x30, 0xA2, 0x0E, 0x96, 0xDE, 0x49, 0x6B, 0x15, 0x79, 0xCE, 0xFB, 0xEE, 0x4A },
            new byte[] { 0xF7, 0x8A, 0x72, 0x5F, 0xCF, 0x7D, 0xDD, 0xAA, 0x39, 0xBE, 0x6D, 0x48, 0x81, 0x90, 0xD0, 0xEC, 0x66, 0x71, 0x95, 0xBC },
            new byte[] { 0x68, 0x12, 0x9A, 0xAB, 0x54, 0x6E, 0x0D, 0xA8, 0x23, 0xFE, 0x07, 0x42, 0xEA, 0xE3, 0x02, 0x6A, 0xDA, 0x07, 0x48, 0xBE },
            new byte[] { 0xAE, 0x2E, 0x8D, 0x33, 0x41, 0x58, 0x2E, 0x47, 0x41, 0x0F, 0xDB, 0x24, 0xCB, 0xD3, 0xC5, 0x00, 0x1B, 0x3C, 0x40, 0xD2 },
            new byte[] { 0xCD, 0xB4, 0xC7, 0x16, 0x3C, 0x12, 0x40, 0x7C, 0x66, 0x4E, 0x4D, 0x4E, 0x2E, 0x2F, 0xEA, 0xD4, 0x8A, 0xD9, 0x37, 0xD3 },
            new byte[] { 0x4B, 0xB9, 0x75, 0x5B, 0x31, 0xFF, 0x6F, 0xD8, 0xBD, 0xAA, 0x6F, 0xD9, 0xF9, 0xFB, 0x15, 0x8B, 0x73, 0x20, 0x11, 0x49 },
            new byte[] { 0xD4, 0x9B, 0x7A, 0x75, 0xED, 0x05, 0x88, 0xF4, 0x2A, 0x89, 0x52, 0xBD, 0x84, 0xB2, 0x90, 0xBC, 0xE6, 0xAF, 0x4A, 0x0F },
            new byte[] { 0xE5, 0x44, 0x7D, 0x79, 0xD6, 0x8B, 0xEC, 0x55, 0xBB, 0x5E, 0xF5, 0x5B, 0x84, 0xA7, 0xC3, 0x13, 0x5F, 0xD0, 0x0E, 0xB2 },
            new byte[] { 0x64, 0x88, 0x46, 0xCD, 0xAC, 0xB5, 0x31, 0x5D, 0x5F, 0x80, 0x35, 0xCC, 0x8A, 0x52, 0x3F, 0xA8, 0xE6, 0x90, 0xDC, 0x75 },
            new byte[] { 0x2F, 0x02, 0x4D, 0xC8, 0x48, 0xFC, 0xDF, 0xBA, 0x73, 0x5E, 0x82, 0x88, 0x09, 0x9D, 0x00, 0x87, 0x2B, 0xED, 0x00, 0x27 },
            new byte[] { 0xC3, 0x42, 0x7F, 0x3A, 0x4B, 0x9C, 0xCE, 0x8F, 0xA0, 0x4D, 0x55, 0x76, 0x03, 0x01, 0xDC, 0xCD, 0xFA, 0x37, 0x56, 0x73 },
            new byte[] { 0xAA, 0x5C, 0xA4, 0x67, 0x47, 0xF9, 0x64, 0x49, 0x4B, 0x83, 0x8A, 0x24, 0xE3, 0xB5, 0x32, 0xE6, 0x39, 0xB3, 0x43, 0x9C },
            new byte[] { 0xC3, 0xF4, 0x6E, 0x4D, 0x3A, 0x30, 0x08, 0x44, 0xD7, 0x2D, 0x56, 0x70, 0xE6, 0xA6, 0x9F, 0x0A, 0x86, 0xC9, 0xBB, 0xF9 },
            new byte[] { 0x40, 0xE8, 0x7F, 0x72, 0x92, 0xCA, 0x36, 0xF5, 0x35, 0x30, 0xBF, 0xA4, 0x60, 0x89, 0x38, 0xD8, 0x77, 0x6E, 0x70, 0x2B },
            new byte[] { 0x9E, 0xCD, 0x04, 0x16, 0x90, 0xD7, 0x9D, 0xF2, 0x50, 0xC8, 0xF6, 0xE9, 0x8F, 0xC7, 0x71, 0x93, 0x80, 0xB0, 0x26, 0xAC },
            new byte[] { 0x74, 0xE1, 0xAD, 0x78, 0x3B, 0xA4, 0x0B, 0x0F, 0xCF, 0x70, 0x9A, 0x74, 0x15, 0xED, 0xCE, 0x94, 0x17, 0xA3, 0x3C, 0xA9 },
            new byte[] { 0x4A, 0x2A, 0xA2, 0xD4, 0x71, 0x38, 0x55, 0x9A, 0x8F, 0xA2, 0x2A, 0x48, 0xE5, 0x57, 0xEA, 0xA2, 0x43, 0x65, 0x13, 0xF9 },
            new byte[] { 0x2F, 0x23, 0x20, 0xAD, 0xAA, 0x87, 0x97, 0x6C, 0x26, 0xC3, 0xF5, 0x86, 0x80, 0x2C, 0x9B, 0x6A, 0x1C, 0xE4, 0x9A, 0xA5 },
            new byte[] { 0xF4, 0x79, 0x16, 0x18, 0xAB, 0x41, 0xD4, 0xE3, 0x73, 0x7F, 0xE9, 0x79, 0x07, 0xA2, 0xC2, 0xB8, 0x59, 0x3D, 0x86, 0x38 },
            new byte[] { 0x9A, 0x65, 0x84, 0x31, 0x29, 0xD1, 0x18, 0x2A, 0x45, 0xF4, 0x28, 0xB9, 0x31, 0x5A, 0xFA, 0xCA, 0xAE, 0xD0, 0xA7, 0xB9 },
            new byte[] { 0x06, 0x0E, 0x28, 0x25, 0x42, 0x51, 0xAC, 0x22, 0x59, 0x49, 0x9E, 0x43, 0xF6, 0xD5, 0x6D, 0x52, 0x28, 0x8F, 0xBA, 0xD0 },
            new byte[] { 0xEC, 0x55, 0xE5, 0xA1, 0xDA, 0x41, 0x22, 0x76, 0x9F, 0x08, 0x98, 0xE4, 0xBB, 0xEA, 0xE3, 0x59, 0x32, 0x84, 0xAF, 0xC1 },
            new byte[] { 0xC0, 0xF7, 0x43, 0x77, 0xB1, 0x56, 0x50, 0xFC, 0xCA, 0xF7, 0x36, 0x89, 0x1C, 0xF9, 0xF4, 0x45, 0xD3, 0xD0, 0x02, 0x27 },
            new byte[] { 0x6D, 0x1D, 0xEE, 0x18, 0x63, 0xD0, 0xB8, 0xBA, 0x2A, 0x19, 0xD6, 0x93, 0x88, 0xF2, 0x27, 0x03, 0xF7, 0x01, 0x97, 0x13 },
            new byte[] { 0x07, 0x25, 0x38, 0x62, 0x0C, 0xEC, 0x14, 0x68, 0x1B, 0xCF, 0x62, 0xE9, 0x65, 0xB4, 0x46, 0xE7, 0x68, 0xEA, 0x82, 0xF4 },
            new byte[] { 0xE7, 0x68, 0x6E, 0x1F, 0x20, 0x62, 0x69, 0xD7, 0x2A, 0xB6, 0x7B, 0xEB, 0xB5, 0xB9, 0x2C, 0xBD, 0x43, 0xCB, 0xC8, 0xF4 },
            new byte[] { 0x68, 0xFF, 0xD2, 0xB6, 0x25, 0xA3, 0x06, 0x7C, 0xFA, 0xE5, 0x47, 0x84, 0x89, 0x83, 0x5F, 0xEC, 0x91, 0x0E, 0x13, 0x93 },
            new byte[] { 0x92, 0xF9, 0xF4, 0x11, 0xB7, 0xE9, 0xDC, 0x7E, 0xDE, 0xE4, 0xF2, 0x22, 0x3A, 0x38, 0xC2, 0x7D, 0x57, 0xC2, 0xDB, 0xB8 },
            new byte[] { 0xB3, 0x9B, 0x96, 0xD9, 0x78, 0xE3, 0xF5, 0xC5, 0xB7, 0x6B, 0x12, 0x07, 0xC8, 0xAA, 0x1D, 0xB1, 0x4C, 0x85, 0x38, 0x39 }};

        // ng decryption tables...
        public static byte[][] PC_NG_DECRYPT_TABLE_HASHES = new byte[][] {
            new byte[] { 0xCE, 0xAB, 0x97, 0x16, 0xBD, 0xEC, 0x4E, 0xB6, 0xB0, 0x28, 0xD3, 0x56, 0x39, 0xE4, 0x5F, 0x2F, 0x3D, 0x8A, 0xC0, 0x3A },
            new byte[] { 0x61, 0x86, 0x8D, 0xFD, 0xF3, 0x86, 0x92, 0xB0, 0xC0, 0x71, 0xF6, 0xB1, 0xC8, 0x09, 0x67, 0x41, 0x22, 0xD4, 0xB3, 0x03 },
            new byte[] { 0xBD, 0x28, 0x5F, 0x22, 0xD5, 0x7C, 0x53, 0xEB, 0x15, 0xC7, 0x28, 0x30, 0x11, 0x2C, 0xD8, 0x0B, 0xF9, 0xDB, 0x0D, 0xC1 },
            new byte[] { 0xCE, 0x23, 0xF5, 0xC5, 0x68, 0x26, 0xF5, 0x3F, 0x78, 0x03, 0xD4, 0xE8, 0x43, 0xCD, 0x19, 0x9A, 0x4D, 0x82, 0xCB, 0xD8 },
            new byte[] { 0xA6, 0xF3, 0xBB, 0xDF, 0x03, 0xFA, 0xCA, 0xF8, 0x93, 0x2D, 0x8E, 0x2E, 0x3B, 0x82, 0x5F, 0x18, 0xD5, 0x4B, 0xF3, 0x8A },
            new byte[] { 0x5B, 0xD1, 0x4C, 0xB2, 0x42, 0x1D, 0x70, 0x11, 0xBA, 0xC1, 0x1E, 0x97, 0xF9, 0xE5, 0x53, 0xE4, 0x80, 0xA4, 0xA9, 0x26 },
            new byte[] { 0x2F, 0x7A, 0x79, 0x53, 0xDB, 0x77, 0x49, 0x9A, 0xDF, 0x2B, 0x76, 0x19, 0xDE, 0x05, 0xFB, 0xBC, 0xCB, 0x37, 0x9C, 0x0D },
            new byte[] { 0xC3, 0x6C, 0xE4, 0x15, 0x62, 0xD8, 0x55, 0xAC, 0x25, 0x17, 0x38, 0x32, 0xD3, 0xFC, 0x1A, 0x13, 0xE1, 0xE4, 0x90, 0x67 },
            new byte[] { 0x31, 0x41, 0xE6, 0xEB, 0xE2, 0xA1, 0xC2, 0xFA, 0x44, 0xD9, 0x72, 0x8E, 0x8D, 0x55, 0x0E, 0xF0, 0x28, 0xB1, 0x19, 0xC6 },
            new byte[] { 0x3D, 0x40, 0x6E, 0xBB, 0xEE, 0x33, 0x93, 0xAB, 0xC8, 0xCE, 0x1C, 0xBE, 0x06, 0x94, 0xB1, 0xCA, 0xF6, 0x72, 0x7F, 0x66 },
            new byte[] { 0x62, 0x1C, 0x68, 0x38, 0x79, 0x92, 0x33, 0xDA, 0xC3, 0xC9, 0x78, 0x5A, 0x35, 0xE7, 0x44, 0x88, 0x16, 0x86, 0x9C, 0x64 },
            new byte[] { 0xD5, 0x93, 0xD9, 0xDD, 0x0C, 0x91, 0xB6, 0x32, 0xA7, 0x96, 0x45, 0x4A, 0x57, 0x6B, 0x05, 0xE2, 0x86, 0xCC, 0xB8, 0x86 },
            new byte[] { 0xC9, 0x33, 0x33, 0xB8, 0x35, 0x07, 0x1D, 0xC4, 0xF0, 0x16, 0xA4, 0xB8, 0x93, 0x60, 0x2B, 0xF5, 0x11, 0x9E, 0x8B, 0x1F },
            new byte[] { 0xDA, 0x99, 0x31, 0x62, 0x1E, 0xE0, 0xAC, 0xBE, 0xF8, 0xF4, 0xF9, 0x95, 0x9B, 0x2D, 0x1D, 0x15, 0x69, 0x57, 0x8D, 0xC2 },
            new byte[] { 0xB9, 0x20, 0xE8, 0x41, 0x15, 0xCA, 0x2B, 0xBF, 0x0A, 0x16, 0x79, 0xE9, 0xDC, 0x7C, 0xD2, 0xD7, 0xF3, 0xF3, 0xEC, 0x99 },
            new byte[] { 0xF6, 0x2B, 0x9D, 0x1C, 0xEE, 0xCE, 0x56, 0xC7, 0x61, 0x28, 0x3A, 0x17, 0x94, 0xF3, 0xA3, 0x09, 0x3B, 0xE7, 0x4F, 0xDE },
            new byte[] { 0x35, 0xCD, 0x71, 0xC3, 0xA4, 0x31, 0x29, 0xA3, 0x57, 0x2A, 0x52, 0xA0, 0x5D, 0x83, 0x95, 0x87, 0xBC, 0x64, 0x0E, 0xA3 },
            new byte[] { 0xD0, 0x71, 0xC0, 0x43, 0x57, 0xCE, 0xF5, 0x86, 0xD8, 0x04, 0xFF, 0x7B, 0x5C, 0x9B, 0x24, 0x7E, 0x4B, 0x05, 0x2B, 0xF0 },
            new byte[] { 0xF5, 0xD1, 0x72, 0xA4, 0x92, 0x78, 0xA9, 0x84, 0x53, 0x49, 0xAD, 0x73, 0x17, 0x8F, 0x2F, 0xEE, 0x8B, 0x0A, 0xAD, 0xBF },
            new byte[] { 0xA5, 0x9E, 0x9B, 0x49, 0x3A, 0xAF, 0x92, 0xDA, 0x8F, 0x4F, 0x3C, 0x20, 0x88, 0x12, 0x89, 0xE1, 0x62, 0x56, 0x95, 0xDA },
            new byte[] { 0xDE, 0x5D, 0x57, 0xA5, 0x08, 0x52, 0xB6, 0xF4, 0x79, 0x8D, 0x9E, 0x52, 0xC4, 0xC5, 0x72, 0x24, 0x5C, 0x13, 0x21, 0xB4 },
            new byte[] { 0x2A, 0x9A, 0x5B, 0x76, 0xF4, 0xBB, 0xD1, 0x56, 0x1F, 0x23, 0xE7, 0xB5, 0x15, 0xA1, 0xAB, 0x1F, 0x6E, 0x33, 0x43, 0xB0 },
            new byte[] { 0xE7, 0x4D, 0x0C, 0x5F, 0x4B, 0x78, 0x6D, 0x32, 0x48, 0x3D, 0x10, 0x0C, 0xA0, 0xAA, 0x4A, 0x1F, 0xCA, 0xB7, 0x4F, 0x50 },
            new byte[] { 0x56, 0xF1, 0xA4, 0xC1, 0x06, 0xDE, 0x83, 0xDA, 0x93, 0x51, 0x32, 0x8B, 0xD1, 0xCA, 0xAA, 0x8C, 0x2E, 0x74, 0xBB, 0x77 },
            new byte[] { 0x1D, 0x50, 0xF9, 0xD2, 0xE6, 0x9B, 0xEC, 0x48, 0xCD, 0x38, 0x58, 0x79, 0x38, 0xE7, 0xC3, 0xEB, 0xCF, 0x77, 0xE7, 0x7B },
            new byte[] { 0x1E, 0xE3, 0x16, 0x88, 0x2A, 0xB9, 0xD7, 0xAE, 0x4A, 0xD9, 0xEB, 0xC8, 0x0D, 0x39, 0xA8, 0x5D, 0xF5, 0x60, 0x19, 0xD1 },
            new byte[] { 0x36, 0x45, 0x6E, 0x8C, 0xD8, 0x1D, 0x0C, 0x6B, 0x3C, 0xA9, 0xA5, 0xEF, 0x2A, 0xFB, 0x08, 0xC4, 0x3E, 0x18, 0x40, 0xAE },
            new byte[] { 0xAA, 0x57, 0x3C, 0xCC, 0x91, 0x64, 0x9C, 0x17, 0xFA, 0xFA, 0xEC, 0x8C, 0x13, 0x7C, 0x43, 0xFD, 0xB1, 0x0C, 0xFC, 0x8E },
            new byte[] { 0x3B, 0xE4, 0xC0, 0xA3, 0xF5, 0x4D, 0x30, 0x75, 0xBD, 0x94, 0xF5, 0x17, 0x41, 0x85, 0x8A, 0xD8, 0x8A, 0x70, 0x14, 0xA6 },
            new byte[] { 0x01, 0x60, 0xBD, 0x1E, 0x73, 0x92, 0x1E, 0xD4, 0x92, 0x03, 0x8F, 0x68, 0x48, 0x9E, 0x6D, 0x53, 0x1F, 0x5A, 0x7D, 0xE6 },
            new byte[] { 0x4C, 0xEA, 0x08, 0xF0, 0x3A, 0xA2, 0x7F, 0xF1, 0xBD, 0x61, 0x31, 0xC1, 0xC3, 0x79, 0xFF, 0x56, 0x04, 0x06, 0x49, 0x04 },
            new byte[] { 0x57, 0x74, 0x33, 0xE6, 0x6C, 0xFA, 0x46, 0xFA, 0x29, 0xB5, 0xF0, 0x26, 0x53, 0xEE, 0x07, 0x40, 0xE2, 0xC2, 0x56, 0xF4 },
            new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F },
            new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F },
            new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F },
            new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 },
            new byte[] { 0xAA, 0x78, 0xF9, 0x79, 0xBD, 0xA6, 0x8B, 0x04, 0x71, 0x07, 0x04, 0x63, 0xBF, 0x39, 0x8F, 0xD9, 0x96, 0xB0, 0x79, 0xB5 },
            new byte[] { 0x65, 0xF2, 0x36, 0xEC, 0xAD, 0xAB, 0x20, 0xA4, 0xD3, 0x20, 0x12, 0xEA, 0xD0, 0xB9, 0xB9, 0x14, 0x94, 0xA8, 0x8D, 0x8A },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x11, 0x7E, 0x60, 0x65, 0x63, 0x55, 0x11, 0xA7, 0x69, 0x7C, 0xEF, 0x0A, 0x80, 0x83, 0x59, 0x65, 0x12, 0x27, 0xB5, 0xFF },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0xA8, 0xE7, 0x2C, 0xEC, 0x82, 0xA7, 0x63, 0x7A, 0x11, 0xBE, 0xA8, 0x49, 0xBA, 0xCB, 0x5C, 0x6A, 0xF0, 0xB1, 0x91, 0xBC },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0xEE, 0x00, 0x26, 0xDB, 0x8E, 0x04, 0x1D, 0x2C, 0x49, 0x3F, 0x96, 0x2E, 0x63, 0x4C, 0x50, 0x6E, 0xED, 0x43, 0x14, 0x86 },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0xA2, 0xC7, 0x69, 0xE5, 0xEF, 0xBA, 0xA2, 0xD3, 0xD8, 0x0B, 0x2C, 0xDE, 0x77, 0xFF, 0x53, 0x23, 0xE1, 0xF7, 0xD6, 0x86 },
            new byte[] { 0x6D, 0xE1, 0x55, 0xDC, 0x31, 0x4C, 0x0A, 0x4A, 0xDB, 0xC1, 0xE2, 0x9B, 0x79, 0x86, 0xB3, 0x58, 0xC3, 0xA9, 0x2B, 0xB2 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0x47, 0xDB, 0xED, 0x88, 0x96, 0xE6, 0x7B, 0xC5, 0xE5, 0xB7, 0xBF, 0x3B, 0xB9, 0x9D, 0x64, 0x95, 0xFF, 0x64, 0x4D, 0x2F },
            new byte[] { 0x50, 0x0D, 0x72, 0xAE, 0xE8, 0x93, 0xE8, 0x3E, 0x55, 0x1F, 0x8F, 0x50, 0xEF, 0x9B, 0xA9, 0x49, 0xCD, 0x5B, 0x55, 0x94 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x17, 0xC4, 0x7D, 0x7C, 0x5F, 0x60, 0x8A, 0xE4, 0xC3, 0x7C, 0x41, 0x40, 0xC9, 0x82, 0x17, 0x58, 0x7D, 0x34, 0x07, 0x4D },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x34, 0x03, 0xAA, 0xC3, 0x70, 0x93, 0xE7, 0xAC, 0xDF, 0x73, 0xC0, 0x4C, 0xBA, 0x74, 0xD6, 0x22, 0xEF, 0x47, 0x44, 0x47 },
            new byte[] { 0x66, 0xA0, 0x4C, 0xDC, 0xD1, 0xFD, 0x45, 0xA4, 0x06, 0x6A, 0xFC, 0xF9, 0x7E, 0x89, 0xCD, 0x4D, 0xFB, 0x90, 0xBD, 0x69 },
            new byte[] { 0x86, 0xF8, 0x6C, 0xD8, 0xBF, 0x0A, 0xE9, 0x1D, 0xBE, 0xAD, 0xA7, 0x03, 0x19, 0x40, 0x43, 0xA3, 0xB0, 0x82, 0x6C, 0x8A },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0x09, 0x96, 0x7E, 0x27, 0x89, 0xDB, 0xB6, 0xF9, 0xA0, 0xEF, 0x4E, 0x18, 0xB6, 0xB3, 0xDD, 0xB8, 0xA9, 0x26, 0x84, 0x7F },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0x0E, 0xCC, 0x47, 0x5D, 0x42, 0x4A, 0xBC, 0x2D, 0xBE, 0xFF, 0x23, 0x81, 0x59, 0x71, 0x16, 0x8A, 0x4D, 0xD4, 0x22, 0x0B },
            new byte[] { 0x48, 0x3C, 0xCE, 0xD1, 0x93, 0x38, 0x36, 0xD6, 0x71, 0x69, 0x5F, 0xDE, 0x6D, 0x8C, 0x42, 0x4D, 0xED, 0x97, 0x9D, 0x41 },
            new byte[] { 0xBA, 0x3E, 0x65, 0x52, 0x88, 0xF2, 0x85, 0xBB, 0xBC, 0x83, 0x31, 0xBE, 0x98, 0xBF, 0x74, 0xA1, 0x40, 0xA9, 0xA4, 0xA4 },
            new byte[] { 0x73, 0x35, 0xEC, 0xB8, 0x47, 0xAD, 0x78, 0xBB, 0xE6, 0x04, 0xB9, 0xB0, 0xFB, 0x1C, 0x9A, 0xB8, 0xC2, 0xC8, 0xBB, 0xC9 },
            new byte[] { 0xC5, 0x61, 0x49, 0x75, 0x11, 0xBB, 0xD4, 0x72, 0xE9, 0x7F, 0xD4, 0x40, 0x76, 0x39, 0x62, 0x92, 0x18, 0x74, 0xEE, 0x4E },
            new byte[] { 0xFC, 0xC2, 0xED, 0x2D, 0xDB, 0xC8, 0xC6, 0x32, 0x69, 0xB4, 0x0B, 0xFB, 0x23, 0xDA, 0x74, 0x52, 0x46, 0x32, 0x57, 0x37 },
            new byte[] { 0x32, 0x3D, 0x56, 0x5F, 0x62, 0x30, 0x7E, 0x60, 0x72, 0xBD, 0x80, 0x8E, 0xA5, 0xED, 0x40, 0x14, 0x4D, 0x05, 0x61, 0xCB },
            new byte[] { 0x10, 0x31, 0xC7, 0xE0, 0x00, 0x14, 0x20, 0xA5, 0x0C, 0x28, 0x29, 0xF5, 0xE8, 0xA9, 0xF5, 0xB5, 0xE3, 0xAD, 0xAF, 0x01 },
            new byte[] { 0x19, 0xF9, 0x24, 0x23, 0xC9, 0xC8, 0x0A, 0x3A, 0xE3, 0x9B, 0xB6, 0x83, 0x19, 0x01, 0x0F, 0x3A, 0x07, 0xAF, 0x19, 0x48 },
            new byte[] { 0x68, 0x3B, 0xF5, 0xB1, 0xBB, 0x4A, 0x1E, 0x84, 0xD2, 0x67, 0x07, 0x35, 0x8F, 0x5C, 0xEE, 0xE4, 0x8D, 0x1A, 0x40, 0x40 },
            new byte[] { 0x96, 0xBE, 0xEA, 0x2F, 0x31, 0x27, 0x79, 0x0D, 0x9D, 0xAA, 0x89, 0x1C, 0x2B, 0x25, 0xF9, 0x3D, 0xC3, 0xF7, 0x8D, 0x33 },
            new byte[] { 0xEB, 0xE1, 0xF6, 0x24, 0x34, 0x9F, 0x34, 0xA4, 0x98, 0x9B, 0x6C, 0xB5, 0x4D, 0x71, 0xC6, 0x17, 0x5E, 0x49, 0xEF, 0x06 },
            new byte[] { 0xB6, 0xF8, 0x03, 0x89, 0x76, 0x2C, 0x30, 0xAF, 0xA4, 0x8B, 0xFA, 0xD5, 0xB2, 0x1E, 0xDE, 0x7B, 0x16, 0xEA, 0xDE, 0x00 },
            new byte[] { 0xE3, 0x5C, 0x12, 0x32, 0xE6, 0xFF, 0x18, 0x07, 0x4F, 0xB2, 0x54, 0x72, 0x0C, 0xC0, 0x02, 0x03, 0x62, 0xFA, 0xCF, 0xB5 },
            new byte[] { 0x22, 0x35, 0xB4, 0xC4, 0x39, 0x5C, 0x8D, 0x32, 0x78, 0xD3, 0x18, 0xFF, 0xA9, 0xA9, 0x49, 0x71, 0x6A, 0x15, 0x89, 0x86 },
            new byte[] { 0xCA, 0xD0, 0xFE, 0xB1, 0x57, 0x03, 0x24, 0xAE, 0xC7, 0x0A, 0xE6, 0x4C, 0x95, 0x77, 0xB9, 0xA2, 0x52, 0x6F, 0x82, 0x14 },
            new byte[] { 0x61, 0x28, 0xA2, 0x29, 0xA6, 0x05, 0x1F, 0x9B, 0x75, 0xEE, 0x05, 0xE6, 0x76, 0x89, 0x4A, 0x93, 0x7A, 0xD9, 0xD3, 0xA7 },
            new byte[] { 0xBA, 0xA2, 0xA7, 0xF0, 0x9D, 0x90, 0xCF, 0x88, 0x2A, 0x10, 0x51, 0x43, 0x1D, 0xB6, 0xE8, 0xB8, 0x14, 0x4B, 0xCC, 0xB1 },
            new byte[] { 0xAC, 0x87, 0x83, 0xBA, 0xB9, 0xBF, 0xB3, 0x82, 0x4B, 0x11, 0x21, 0x51, 0x10, 0x54, 0xC9, 0x8D, 0x1C, 0x91, 0x57, 0x93 },
            new byte[] { 0x5C, 0xD9, 0x28, 0xDE, 0x94, 0xA8, 0xA7, 0x80, 0x38, 0x40, 0x85, 0x7B, 0x9B, 0x90, 0x4C, 0xB9, 0xAC, 0x46, 0x1A, 0xE4 },
            new byte[] { 0x1B, 0xB9, 0x0E, 0x90, 0x54, 0x94, 0x30, 0xD7, 0xB6, 0xED, 0x22, 0x73, 0xE5, 0x0E, 0xD9, 0xF8, 0xD1, 0x89, 0x07, 0xC6 },
            new byte[] { 0xB5, 0xFB, 0x97, 0x72, 0x29, 0x80, 0x46, 0x9E, 0x98, 0x32, 0x16, 0xA8, 0xDD, 0x67, 0xE3, 0x08, 0xE5, 0x2F, 0xD4, 0x7B },
            new byte[] { 0x99, 0xD7, 0x23, 0x19, 0xEB, 0x25, 0x35, 0x50, 0x85, 0xB2, 0x07, 0xF6, 0x35, 0x05, 0x9A, 0x1E, 0xB7, 0x70, 0xEA, 0xB0 },
            new byte[] { 0x43, 0x98, 0x81, 0x8B, 0x29, 0x39, 0xB0, 0xA8, 0x4A, 0xE9, 0xF3, 0x5E, 0x34, 0x08, 0xB6, 0x06, 0x43, 0xC9, 0x65, 0x9A },
            new byte[] { 0x22, 0x29, 0x15, 0x79, 0xF0, 0x0E, 0x98, 0x23, 0x40, 0x02, 0xE7, 0x42, 0x73, 0xFE, 0xC6, 0xB9, 0x19, 0xD1, 0x75, 0x95 },
            new byte[] { 0xC4, 0x01, 0xA3, 0xB4, 0xDA, 0x0B, 0xBA, 0xA3, 0x0D, 0x7A, 0xEF, 0x7D, 0xD9, 0x3D, 0xC3, 0x30, 0x6D, 0xC0, 0x92, 0x58 },
            new byte[] { 0x0E, 0xBB, 0x73, 0x38, 0xF7, 0x1B, 0x31, 0x63, 0x3B, 0x08, 0x61, 0x2D, 0xF1, 0x70, 0xAD, 0x52, 0x61, 0x9E, 0xE8, 0x35 },
            new byte[] { 0x68, 0xA8, 0xC5, 0x39, 0x6C, 0x87, 0x6D, 0xE1, 0x60, 0x7B, 0x1C, 0x78, 0xD2, 0x75, 0xF0, 0xB0, 0xD0, 0x15, 0x00, 0xFB },
            new byte[] { 0x98, 0xCC, 0xA6, 0xC6, 0x2C, 0xE2, 0x56, 0xFE, 0x15, 0xD0, 0x93, 0xDE, 0x11, 0x0C, 0xDA, 0x11, 0x7C, 0x5D, 0x9D, 0x1D },
            new byte[] { 0x8E, 0xE8, 0x1A, 0x0D, 0x52, 0xAA, 0x76, 0x2D, 0xC4, 0x93, 0x79, 0xE9, 0xB6, 0x44, 0x63, 0xD9, 0x64, 0x76, 0x8E, 0xF1 },
            new byte[] { 0xEC, 0xB5, 0x72, 0x84, 0x60, 0x55, 0xAF, 0xCE, 0x9A, 0x1E, 0x4D, 0x8B, 0x21, 0x87, 0x5E, 0x25, 0xBE, 0x0C, 0xC0, 0x4E },
            new byte[] { 0xB6, 0xF4, 0xF6, 0xBC, 0x64, 0x34, 0xC3, 0xB5, 0x2D, 0xDE, 0xBA, 0xF2, 0xCA, 0xBF, 0x7F, 0x52, 0xCD, 0xE5, 0x45, 0xC1 },
            new byte[] { 0x33, 0xE2, 0xBE, 0xBD, 0xAA, 0x14, 0x04, 0xC6, 0x23, 0x96, 0xF4, 0x69, 0x78, 0x33, 0x48, 0xB6, 0x5D, 0x1A, 0xF0, 0xC0 },
            new byte[] { 0xEE, 0x0B, 0x31, 0xC0, 0x16, 0x73, 0x23, 0xD7, 0xE4, 0x82, 0xB1, 0xE2, 0x38, 0xDE, 0x99, 0xD7, 0x92, 0x66, 0x59, 0xAB },
            new byte[] { 0x8F, 0x9E, 0xC7, 0xAB, 0x3F, 0x5B, 0x97, 0xCF, 0xAC, 0x1D, 0xBA, 0x83, 0x88, 0x67, 0x90, 0xEF, 0xE1, 0xEF, 0xA4, 0xE1 },
            new byte[] { 0x2C, 0xF3, 0xF2, 0x12, 0x07, 0xDD, 0x8F, 0x2C, 0xBA, 0x24, 0x10, 0x4F, 0xDA, 0x7B, 0xEC, 0x21, 0x01, 0x16, 0xD4, 0x45 },
            new byte[] { 0xB9, 0xE1, 0x5D, 0xE5, 0xA0, 0x83, 0xC1, 0xAA, 0x9E, 0xAB, 0x09, 0x9B, 0x7E, 0x09, 0x39, 0x5E, 0x2C, 0xE0, 0x2B, 0xE4 },
            new byte[] { 0x43, 0x23, 0xB0, 0xAA, 0x5F, 0x01, 0x51, 0x74, 0x89, 0x04, 0xA4, 0xB2, 0xC4, 0x03, 0x3D, 0x5E, 0x9A, 0xF0, 0x1D, 0xBB }};

        // hash lookup-table...
        public static byte[] PC_LUT_HASH = new byte[] { 0x88, 0xD3, 0x79, 0x3B, 0x8E, 0x7A, 0x6C, 0xAC, 0xAA, 0x8B, 0x89, 0x28, 0x97, 0xBE, 0x72, 0x8D, 0x9E, 0x7F, 0xBA, 0xD4 };
    }



    public class GTA5NGLUT
    {
        public byte[][] LUT0;
        public byte[][] LUT1;
        public byte[] Indices;

        public GTA5NGLUT()
        {
            LUT0 = new byte[256][];
            for (int i = 0; i < 256; i++)
                LUT0[i] = new byte[256];

            LUT1 = new byte[256][];
            for (int i = 0; i < 256; i++)
                LUT1[i] = new byte[256];

            Indices = new byte[65536];
        }

        public byte LookUp(uint value)
        {
            uint h16 = (value & 0xFFFF0000) >> 16;
            uint l8 = (value & 0x0000FF00) >> 8;
            uint l0 = (value & 0x000000FF) >> 0;
            return LUT0[LUT1[Indices[h16]][l8]][l0];
        }
    }

    public static class HashSearch
    {
        private const long BLOCK_LENGTH = 1048576;
        private const long ALIGN_LENGTH = 8;

        public static byte[] SearchHash(Stream stream, byte[] hash, int length = 32)
        {
            return SearchHashes(stream, new List<byte[]> { hash }, length)[0];
        }

        public static byte[][] SearchHashes(Stream stream, IList<byte[]> hashes, int length = 32)
        {
            var result = new byte[hashes.Count][];

            Parallel.For(0, (stream.Length / BLOCK_LENGTH), (long k) => {

                var hashProvider = new SHA1CryptoServiceProvider();
                var buffer = new byte[length];
                for (long i = 0; i < (BLOCK_LENGTH / ALIGN_LENGTH); i++)
                {
                    var position = k * BLOCK_LENGTH + i * ALIGN_LENGTH;
                    if (position >= stream.Length)
                        continue;

                    lock (stream)
                    {
                        stream.Position = position;
                        stream.Read(buffer, 0, length);
                    }

                    var hash = hashProvider.ComputeHash(buffer);
                    for (int j = 0; j < hashes.Count; j++)
                        if (hash.SequenceEqual(hashes[j]))
                            result[j] = (byte[])buffer.Clone();
                }


            });

            return result;
        }
    }


    public class RandomGaussRow
    {
        //private bool[] A = new bool[1024];
        private ulong[] A = new ulong[16];
        public bool B;


        public bool GetA(int idx)
        {
            int lidx = idx / 64;
            int bidx = idx % 64;
            return ((A[lidx] >> bidx) & 0x1) != 0;
        }

        public void SetA(int idx)
        {
            int lidx = idx / 64;
            int bidx = idx % 64;
            A[lidx] |= (ulong)1 << bidx;
        }

        public bool GetB()
        {
            return B;
        }

        public void SetB()
        {
            this.B = true;
        }

        public static RandomGaussRow operator ^(RandomGaussRow r1, RandomGaussRow r2)
        {
            var newRow = new RandomGaussRow();
            for (int i = 0; i < 16; i++)
                newRow.A[i] = r1.A[i] ^ r2.A[i];
            newRow.B = r1.B ^ r2.B;
            return newRow;
        }
    }

    public class RandomGauss
    {
        private const int TEST_ITERATIONS = 100000;

        public static bool[] Solve(
            uint[][] tables,
            int inByte0, int inByte1, int inByte2, int inByte3,
            int outByte, int outBit)
        {
            var noKey = new uint[] { 0, 0, 0, 0 };
            var random = new Random();

            var pivots = new List<RandomGaussRow>();

            var firstPivot = new RandomGaussRow();
            firstPivot.SetA(0);
            firstPivot.SetB();
            pivots.Add(firstPivot);

            var buf_encrypted = new byte[16];
            for (int pivotIdx = 1; pivotIdx < 1024; pivotIdx++)
            {
                while (true)
                {
                    random.NextBytes(buf_encrypted);

                    // decrypt                   
                    var buf_decrypted = GTACrypto.DecryptNGRoundA(
                        buf_encrypted,
                        noKey,
                        tables);

                    // make row
                    var row = new RandomGaussRow();
                    //row.A[0 + buf_decrypted[inByte0]] = true;
                    //row.A[256 + buf_decrypted[inByte1]] = true;
                    //row.A[512 + buf_decrypted[inByte2]] = true;
                    //row.A[768 + buf_decrypted[inByte3]] = true;
                    //row.B = (buf_encrypted[outByte] & (1 << outBit)) != 0;
                    row.SetA(0 + buf_decrypted[inByte0]);
                    row.SetA(256 + buf_decrypted[inByte1]);
                    row.SetA(512 + buf_decrypted[inByte2]);
                    row.SetA(768 + buf_decrypted[inByte3]);
                    if ((buf_encrypted[outByte] & (1 << outBit)) != 0)
                        row.SetB();

                    if (pivotIdx == 0x2ff)
                    {
                        row = new RandomGaussRow();
                        row.SetA(0x2ff);
                        row.SetB();
                    }
                    if (pivotIdx == 0x3ff)
                    {
                        row = new RandomGaussRow();
                        row.SetA(0x3ff);
                        row.SetB();
                    }

                    // apply pivotIdx-1 pivots
                    for (int k = 0; k < pivotIdx; k++)
                    {
                        if (row.GetA(k))
                        {
                            row ^= pivots[k];
                            //var ppp = pivots[k];
                            //for (int p = 0; p < 1024; p++)
                            //    row.A[p] ^= ppp.A[p];
                            //row.B ^= ppp.B;
                        }
                    }

                    // check if this row is a new pivot
                    if (row.GetA(pivotIdx))
                    {
                        pivots.Add(row);
                        //    Console.WriteLine("Found pivot for column " + pivotIdx.ToString());
                        break;
                    }
                }
            }

            var result = new bool[1024];
            for (int j = 1023; j >= 0; j--)
            {
                bool val = pivots[j].GetB();
                result[j] = val;
                for (int k = 0; k < j; k++)
                {
                    if (pivots[k].GetA(j))
                        pivots[k].B ^= val;
                }
            }

            return result;
        }

        public static uint[][] Solve(uint[][] tables)
        {
            var result = new uint[16][];
            for (int tabIdx = 0; tabIdx < 16; tabIdx++)
            {
                result[tabIdx] = new uint[256];
            }

            //for (int bitIdx = 0; bitIdx < 128; bitIdx++)
            Parallel.For(0, 128, (int bitIdx) =>
            {
                int outByte = bitIdx / 8;
                int uintIdx = outByte / 4;

                int inByte0 = 4 * uintIdx + 0;
                int inByte1 = 4 * uintIdx + 1;
                int inByte2 = 4 * uintIdx + 2;
                int inByte3 = 4 * uintIdx + 3;
                int outBit = bitIdx % 8;
                int z = bitIdx % 32;

                var bitResult = Solve(tables, inByte0, inByte1, inByte2, inByte3, outByte, outBit);
                lock (result)
                {
                    for (int i = 0; i < 256; i++)
                    {
                        if (bitResult[0 + i])
                            result[inByte0][i] |= (uint)(1 << z);
                        if (bitResult[256 + i])
                            result[inByte1][i] |= (uint)(1 << z);
                        if (bitResult[512 + i])
                            result[inByte2][i] |= (uint)(1 << z);
                        if (bitResult[768 + i])
                            result[inByte3][i] |= (uint)(1 << z);
                    }
                }

            });

            return result;
        }

    }

    public class LookUpTableGenerator
    {
        public static GTA5NGLUT[] BuildLUTs2(uint[][] tables)
        {
            var temp = new byte[16][];
            for (int i = 0; i < 16; i++)
                temp[i] = new byte[65536];

            var result = new GTA5NGLUT[16];
            for (int i = 0; i < 16; i++)
            {
                result[i] = new GTA5NGLUT();
                //result[i].Tables = new byte[256][];
                //result[i].LUT = new byte[16777216];
            }

            var tempLUTS = new byte[16][];
            for (int i = 0; i < 16; i++)
                tempLUTS[i] = new byte[16777216];

            var t0 = tables[0];
            var t1 = tables[1];
            var t2 = tables[2];
            var t3 = tables[3];
            var t4 = tables[4];
            var t5 = tables[5];
            var t6 = tables[6];
            var t7 = tables[7];
            var t8 = tables[8];
            var t9 = tables[9];
            var t10 = tables[10];
            var t11 = tables[11];
            var t12 = tables[12];
            var t13 = tables[13];
            var t14 = tables[14];
            var t15 = tables[15];

            Parallel.For(0, 0x100, (long k1) =>
            {
                for (long k2 = 0; k2 < 0x1000000; k2++)
                {
                    long i = k1 * 0x1000000 + k2;

                    byte b0 = (byte)((i >> 0) & 0xFF);
                    byte b1 = (byte)((i >> 8) & 0xFF);
                    byte b2 = (byte)((i >> 16) & 0xFF);
                    byte b3 = (byte)((i >> 24) & 0xFF);

                    var x1 =
                         t0[b0] ^
                         t7[b1] ^
                         t10[b2] ^
                         t13[b3];
                    var x2 =
                        t1[b0] ^
                        t4[b1] ^
                        t11[b2] ^
                        t14[b3];
                    var x3 =
                        t2[b0] ^
                        t5[b1] ^
                        t8[b2] ^
                        t15[b3];
                    var x4 =
                        t3[b0] ^
                        t6[b1] ^
                        t9[b2] ^
                        t12[b3];

                    // the first LUT-compression step is built-it
                    // because it would take 4GB ram per data byte (and there are 16)

                    if (x1 < 65536)
                    {
                        temp[0][x1] = b0;
                        temp[7][x1] = b1;
                        temp[10][x1] = b2;
                        temp[13][x1] = b3;
                    }

                    if (x2 < 65536)
                    {
                        temp[1][x2] = b0;
                        temp[4][x2] = b1;
                        temp[11][x2] = b2;
                        temp[14][x2] = b3;
                    }

                    if (x3 < 65536)
                    {
                        temp[2][x3] = b0;
                        temp[5][x3] = b1;
                        temp[8][x3] = b2;
                        temp[15][x3] = b3;
                    }

                    if (x4 < 65536)
                    {
                        temp[3][x4] = b0;
                        temp[6][x4] = b1;
                        temp[9][x4] = b2;
                        temp[12][x4] = b3;
                    }

                    if ((x1 & 0x000000FF) == 0)
                    {
                        tempLUTS[0][x1 >> 8] = b0;
                        tempLUTS[7][x1 >> 8] = b1;
                        tempLUTS[10][x1 >> 8] = b2;
                        tempLUTS[13][x1 >> 8] = b3;
                    }

                    if ((x2 & 0x000000FF) == 0)
                    {
                        tempLUTS[1][x2 >> 8] = b0;
                        tempLUTS[4][x2 >> 8] = b1;
                        tempLUTS[11][x2 >> 8] = b2;
                        tempLUTS[14][x2 >> 8] = b3;
                    }

                    if ((x3 & 0x000000FF) == 0)
                    {
                        tempLUTS[2][x3 >> 8] = b0;
                        tempLUTS[5][x3 >> 8] = b1;
                        tempLUTS[8][x3 >> 8] = b2;
                        tempLUTS[15][x3 >> 8] = b3;
                    }

                    if ((x4 & 0x000000FF) == 0)
                    {
                        tempLUTS[3][x4 >> 8] = b0;
                        tempLUTS[6][x4 >> 8] = b1;
                        tempLUTS[9][x4 >> 8] = b2;
                        tempLUTS[12][x4 >> 8] = b3;
                    }
                }
            });

            for (int i = 0; i < 16; i++)
            {
                result[i].LUT0 = new byte[256][];
                for (int blockIdx = 0; blockIdx < 256; blockIdx++)
                {

                    var xl = new byte[256];
                    for (int k = 0; k < 256; k++)
                    {
                        xl[k] = temp[i][256 * blockIdx + k];
                    }

                    result[i].LUT0[xl[0]] = xl;
                }
            }

            // compress tables...
            // length from 2^24 -> 2^16
            for (int i = 0; i < 16; i++)
            {
                GTA5NGLUT lut = result[i];
                lut.LUT1 = new byte[256][];
                lut.Indices = new byte[65536];

                for (int blockIdx = 0; blockIdx < 256; blockIdx++)
                {
                    var xl = new byte[256];
                    for (int k = 0; k < 256; k++)
                    {
                        xl[k] = tempLUTS[i][256 * blockIdx + k];
                    }

                    lut.LUT1[xl[0]] = xl;
                }
                for (int blockIdx = 0; blockIdx < 65536; blockIdx++)
                {
                    lut.Indices[blockIdx] = tempLUTS[i][256 * blockIdx];
                }
            }

            return result;
        }
    }



    public class CryptoIO
    {
        public static byte[][] ReadNgKeys(string fileName)
        {
            byte[][] result;

            var fs = new FileStream(fileName, FileMode.Open);
            var rd = new DataReader(fs);

            result = new byte[101][];
            for (int i = 0; i < 101; i++)
            {
                result[i] = rd.ReadBytes(272);
            }

            fs.Close();

            return result;
        }
        public static byte[][] ReadNgKeys(byte[] data)
        {
            byte[][] result;

            var rd = new DataReader(new MemoryStream(data));

            result = new byte[101][];
            for (int i = 0; i < 101; i++)
            {
                result[i] = rd.ReadBytes(272);
            }


            return result;
        }


        public static void WriteNgKeys(string fileName, byte[][] keys)
        {
            //var fs = new FileStream(fileName, FileMode.Create);
            //var wr = new DataWriter(fs);
            var ms = new MemoryStream();
            var wr = new DataWriter(ms);

            for (int i = 0; i < 101; i++)
            {
                wr.Write(keys[i]);
            }

            //fs.Close();
            using (var fs = new FileStream(fileName, FileMode.Create))
            {
                ms.Position = 0;
                ms.CopyTo(fs);
            }
            
        }

        public static uint[][][] ReadNgTables(string fileName)
        {
            uint[][][] result;

            var fs = new FileStream(fileName, FileMode.Open);
            var rd = new DataReader(fs);

            // 17 rounds...
            result = new uint[17][][];
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                result[i] = new uint[16][];
                for (int j = 0; j < 16; j++)
                {
                    // 256 entries...
                    result[i][j] = new uint[256];
                    for (int k = 0; k < 256; k++)
                    {
                        result[i][j][k] = rd.ReadUInt32();
                    }
                }
            }

            fs.Close();

            return result;
        }
        public static uint[][][] ReadNgTables(byte[] data)
        {
            uint[][][] result;

            var rd = new DataReader(new MemoryStream(data));

            // 17 rounds...
            result = new uint[17][][];
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                result[i] = new uint[16][];
                for (int j = 0; j < 16; j++)
                {
                    // 256 entries...
                    result[i][j] = new uint[256];
                    for (int k = 0; k < 256; k++)
                    {
                        result[i][j][k] = rd.ReadUInt32();
                    }
                }
            }

            return result;
        }



        public static void WriteNgTables(string fileName, uint[][][] tableData)
        {
            //var fs = new FileStream(fileName, FileMode.Create);
            //var wr = new DataWriter(fs);
            var ms = new MemoryStream();
            var wr = new DataWriter(ms);

            // 17 rounds...
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                for (int j = 0; j < 16; j++)
                {
                    // 256 entries...
                    for (int k = 0; k < 256; k++)
                    {
                        wr.Write(tableData[i][j][k]);
                    }
                }
            }

            //fs.Close();

            using (var fs = new FileStream(fileName, FileMode.Create))
            {
                ms.Position = 0;
                ms.CopyTo(fs);
            }
        }

        public static GTA5NGLUT[][] ReadNgLuts(string fileName)
        {
            GTA5NGLUT[][] result;

            var fs = new FileStream(fileName, FileMode.Open);
            var rd = new DataReader(fs);

            // 17 rounds...
            result = new GTA5NGLUT[17][];
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                result[i] = new GTA5NGLUT[16];
                for (int j = 0; j < 16; j++)
                {
                    result[i][j] = new GTA5NGLUT();

                    // first compression step (2^32 -> 2^24)
                    result[i][j].LUT0 = new byte[256][];
                    for (int k = 0; k < 256; k++)
                    {
                        //result[i][j].LUT0[k] = new byte[256];
                        //for (int l = 0; l < 256; l++)
                        //    result[i][j].LUT0[k][l] = rd.ReadByte();
                        result[i][j].LUT0[k] = rd.ReadBytes(256);
                    }

                    // second compression step (2^24 -> 2^16)
                    result[i][j].LUT1 = new byte[256][];
                    for (int k = 0; k < 256; k++)
                    {
                        //result[i][j].LUT1[k] = new byte[256];
                        //for (int l = 0; l < 256; l++)
                        //    result[i][j].LUT1[k][l] = rd.ReadByte();
                        result[i][j].LUT1[k] = rd.ReadBytes(256);
                    }

                    // indices
                    //result[i][j].Indices = new byte[65536];
                    //for (int k = 0; k < 65536; k++)
                    //    result[i][j].Indices[k] = rd.ReadByte();
                    result[i][j].Indices = rd.ReadBytes(65536);
                }
            }


            fs.Close();

            return result;
        }
        public static GTA5NGLUT[][] ReadNgLuts(byte[] data)
        {
            GTA5NGLUT[][] result;

            var rd = new DataReader(new MemoryStream(data));

            // 17 rounds...
            result = new GTA5NGLUT[17][];
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                result[i] = new GTA5NGLUT[16];
                for (int j = 0; j < 16; j++)
                {
                    result[i][j] = new GTA5NGLUT();

                    // first compression step (2^32 -> 2^24)
                    result[i][j].LUT0 = new byte[256][];
                    for (int k = 0; k < 256; k++)
                    {
                        //result[i][j].LUT0[k] = new byte[256];
                        //for (int l = 0; l < 256; l++)
                        //    result[i][j].LUT0[k][l] = rd.ReadByte();
                        result[i][j].LUT0[k] = rd.ReadBytes(256);
                    }

                    // second compression step (2^24 -> 2^16)
                    result[i][j].LUT1 = new byte[256][];
                    for (int k = 0; k < 256; k++)
                    {
                        //result[i][j].LUT1[k] = new byte[256];
                        //for (int l = 0; l < 256; l++)
                        //    result[i][j].LUT1[k][l] = rd.ReadByte();
                        result[i][j].LUT1[k] = rd.ReadBytes(256);
                    }

                    // indices
                    //result[i][j].Indices = new byte[65536];
                    //for (int k = 0; k < 65536; k++)
                    //    result[i][j].Indices[k] = rd.ReadByte();
                    result[i][j].Indices = rd.ReadBytes(65536);
                }
            }


            return result;
        }

        public static void WriteLuts(string fileName, GTA5NGLUT[][] lutData)
        {
            //var fs = new FileStream(fileName, FileMode.Create);
            //var wr = new DataWriter(fs);
            var ms = new MemoryStream();
            var wr = new DataWriter(ms);

            // 17 rounds...
            for (int i = 0; i < 17; i++)
            {
                // 16 bytes...
                for (int j = 0; j < 16; j++)
                {
                    GTA5NGLUT lut = lutData[i][j];

                    // first compression step (2^32 -> 2^24)
                    for (int k = 0; k < 256; k++)
                        for (int l = 0; l < 256; l++)
                            wr.Write(lut.LUT0[k][l]);

                    // second compression step (2^24 -> 2^16)
                    for (int k = 0; k < 256; k++)
                        for (int l = 0; l < 256; l++)
                            wr.Write(lut.LUT1[k][l]);

                    // indices
                    for (int k = 0; k < 65536; k++)
                        wr.Write(lut.Indices[k]);
                }
            }

            //fs.Close();

            using (var fs = new FileStream(fileName, FileMode.Create))
            {
                ms.Position = 0;
                ms.CopyTo(fs);
            }
        }
    }



    public class GTA5Hash
    {
        public static byte[] LUT;

        static GTA5Hash()
        {
            // setup constants...
            LUT = GTA5Keys.PC_LUT;
        }

        public static uint CalculateHash(string text)
        {
            /*
             
                func CalculateHash(keys Keys, filename string) (result uint32) {
                    for _, c := range filename {
                        temp := 1025 * (uint32(keys.hashLookup[int(c)]) + result)
                        result = (temp >> 6) ^ temp
                    }
                    return 32769 * (((9 * result) >> 11) ^ 9*result)
                }

             */


            uint result = 0;
            for (int index = 0; index < text.Length; index++)
            {
                var temp = 1025 * (LUT[text[index]] + result);
                result = (temp >> 6) ^ temp;
            }

            return 32769 * ((9 * result >> 11) ^ (9 * result));
        }
    }


}
